<!--
 * @Author: 刘翔
 * @Date: 2025-08-15 15:03:26
 * @LastEditTime: 2025-08-20 14:49:57
 * @LastEditors: 刘翔
 * @Description:多表头表格
 * @FilePath: \建达文件\ts-demo\ts-demo\src\pptHome\components\DataTableMany.vue
-->

<template>
  <div class="data-table-many">
    <table class="medical-table">
      <thead>
        <!-- 一级表头 -->
        <tr class="header-row-1">
          <th v-for="col in columns.columns1" :key="col.prop" :rowspan="2" class="header-cell level-1" :style="{ width: col.widthPercent + '%', fontSize: col.headerFontSize + 'px' }">
            {{ col.label }}
          </th>
          <!-- 二级表头组 -->
          <th
            v-for="group in columns.columns2"
            :key="group.prop"
            :colspan="group.columns.length"
            class="header-cell level-1 group-header"
            :style="{ fontSize: group.headerFontSize + 'px', width: group.widthPercent + '%' }"
          >
            {{ group.label }}
          </th>
        </tr>
        <!-- 二级表头 -->
        <tr class="header-row-2">
          <template v-for="group in columns.columns2" :key="group.prop">
            <th
              v-for="col in group.columns"
              :key="col.prop"
              class="header-cell level-2"
              :style="{ fontSize: (group.headerFontSize || 14) + 'px', width: group.widthPercent / group.columns.length + '%' }"
            >
              {{ col.label }}
            </th>
          </template>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(row, index) in tableData" :key="index" class="data-row" :class="{ 'row-even': index % 2 === 0, 'row-odd': index % 2 === 1 }">
          <td v-for="col in columns.columns1" :key="col.prop" class="data-cell medical-group" :style="{ fontSize: col.contentFontSize + 'px', width: col.widthPercent + '%' }">
            {{ row[col.prop] }}
          </td>
          <!-- 二级数据 -->
          <template v-for="group in columns.columns2" :key="group.prop">
            <td v-for="col in group.columns" :key="col.prop" class="data-cell" :style="{ fontSize: (group.contentFontSize || 14) + 'px', width: group.widthPercent / group.columns.length + '%' }">
              {{ formatValue(col.prop, row[col.prop]) }}
            </td>
          </template>
        </tr>
      </tbody>
    </table>
  </div>
</template>
<script>
export default {
  name: 'DataTableMany',
  props: {
    // 表头背景色
    headerBgColor: {
      type: String,
      default: '#4874cb',
    },
    // PPT导出配置
    pptOptions: {
      type: Object,
      default: () => ({
        x: 0.4, // X轴位置
        y: 0.4, // Y轴位置
        w: 9.3, // 宽度
        h: 4.8, // 高度
        title: {
          // 标题配置
          x: 0.5,
          y: 0.5,
          fontSize: 24,
          color: '363636',
          bold: true,
        },
        table: {
          // 表格配置 - 多表头场景建议不设置固定colW，让系统自动计算
          colW: [],
          rowH: 0.2, // 单行高度
          // 表格内容配置
          content: {
            fontSize: 8,
            color: '000000',
            bold: true,
          },
          // 表格标题配置
          title: {
            fontSize: 8,
            color: 'ffffff',
          },
          // 表格边框样式
          borderStyle: {
            color: '000000',
          },
          // 表格垂直对齐方式(middle, top, bottom)
          valign: 'middle',
          // 表格水平对齐方式(left, center, right)
          align: 'center',
          // 自动分页
          autoPage: true,
          // 自动分页标题是否显示
          autoPageRepeatHeader: true,
          // 自动分页标题行数
          autoPageHeaderRows: 2, // 多表头需要2行
        },
      }),
    },
    tableData: {
      type: Array,
      default: () => [
        {
          医疗组: '心血管内科二组',
          病例数: 762,
          病组数: 73,
          CMI: 1.17,
          总权重: 888.91,
          本院例均费用: 9946.07,
          平均住院日: 5.49,
          药品费占比: 9.02,
          材料费占比: 30.73,
          总点数: 91982.28,
          '合计盈亏(万元)': -9.43,
          '拨付金额(万元)': 748.16,
          例均盈亏: -123.75,
        },
        {
          医疗组: '胸部疾病诊疗中心二组',
          病例数: 616,
          病组数: 54,
          CMI: 1.25,
          总权重: 768.61,
          本院例均费用: 10558.12,
          平均住院日: 6.11,
          药品费占比: 14.73,
          材料费占比: 22.21,
          总点数: 78335.91,
          '合计盈亏(万元)': -15.51,
          '拨付金额(万元)': 634.38,
          例均盈亏: -251.82,
        },
        {
          医疗组: '消化内科二组',
          病例数: 1045,
          病组数: 68,
          CMI: 0.72,
          总权重: 752.86,
          本院例均费用: 6208.01,
          平均住院日: 3.58,
          药品费占比: 19.32,
          材料费占比: 6.01,
          总点数: 76612.68,
          '合计盈亏(万元)': -25.5,
          '拨付金额(万元)': 623.24,
          例均盈亏: -243.98,
        },
        {
          医疗组: '消化内科一组',
          病例数: 979,
          病组数: 62,
          CMI: 0.74,
          总权重: 724.1,
          本院例均费用: 5860.64,
          平均住院日: 3.52,
          药品费占比: 14.25,
          材料费占比: 8.62,
          总点数: 72707.68,
          '合计盈亏(万元)': 18.8,
          '拨付金额(万元)': 592.56,
          例均盈亏: 192.07,
        },
        {
          医疗组: '普外科二组',
          病例数: 604,
          病组数: 98,
          CMI: 0.96,
          总权重: 579.95,
          本院例均费用: 7420.67,
          平均住院日: 5.36,
          药品费占比: 14.76,
          材料费占比: 14.94,
          总点数: 55949.84,
          '合计盈亏(万元)': 5.51,
          '拨付金额(万元)': 453.71,
          例均盈亏: 91.27,
        },
        {
          医疗组: '呼吸与危重症医学科一',
          病例数: 626,
          病组数: 69,
          CMI: 0.87,
          总权重: 546.2,
          本院例均费用: 9068.47,
          平均住院日: 9.36,
          药品费占比: 18.59,
          材料费占比: 2.51,
          总点数: 65628.58,
          '合计盈亏(万元)': -37.29,
          '拨付金额(万元)': 528.89,
          例均盈亏: -595.64,
        },
        {
          医疗组: '胸部疾病诊疗中心三组',
          病例数: 436,
          病组数: 47,
          CMI: 1.24,
          总权重: 538.89,
          本院例均费用: 9932.65,
          平均住院日: 5.27,
          药品费占比: 17.14,
          材料费占比: 20.32,
          总点数: 54626.3,
          '合计盈亏(万元)': 9.63,
          '拨付金额(万元)': 442.69,
          例均盈亏: 220.83,
        },
        {
          医疗组: '心血管内科一组',
          病例数: 466,
          病组数: 54,
          CMI: 1.06,
          总权重: 492.5,
          本院例均费用: 8959.64,
          平均住院日: 5.96,
          药品费占比: 9.15,
          材料费占比: 24.27,
          总点数: 50537.57,
          '合计盈亏(万元)': -7.46,
          '拨付金额(万元)': 409.83,
          例均盈亏: -159.98,
        },
        {
          医疗组: '关节/创伤骨科一组',
          病例数: 249,
          病组数: 47,
          CMI: 1.76,
          总权重: 437.93,
          本院例均费用: 11353.96,
          平均住院日: 7.64,
          药品费占比: 9.61,
          材料费占比: 31.61,
          总点数: 39986.53,
          '合计盈亏(万元)': 40.02,
          '拨付金额(万元)': 322.73,
          例均盈亏: 1607.15,
        },
        {
          医疗组: '神经内科一组',
          病例数: 538,
          病组数: 72,
          CMI: 0.79,
          总权重: 427.4,
          本院例均费用: 6031.35,
          平均住院日: 7.63,
          药品费占比: 15.88,
          材料费占比: 4.25,
          总点数: 40565.7,
          '合计盈亏(万元)': 4.44,
          '拨付金额(万元)': 328.74,
          例均盈亏: 82.44,
        },
        {
          医疗组: '脊柱/创伤骨科三组',
          病例数: 206,
          病组数: 41,
          CMI: 1.96,
          总权重: 403.04,
          本院例均费用: 14576.67,
          平均住院日: 8.07,
          药品费占比: 13.99,
          材料费占比: 32.05,
          总点数: 39005.18,
          '合计盈亏(万元)': 13.67,
          '拨付金额(万元)': 313.71,
          例均盈亏: 663.44,
        },
        {
          医疗组: '脊柱/创伤骨科一组',
          病例数: 243,
          病组数: 47,
          CMI: 1.63,
          总权重: 395.18,
          本院例均费用: 13267.64,
          平均住院日: 8.83,
          药品费占比: 11.43,
          材料费占比: 32.55,
          总点数: 39631.12,
          '合计盈亏(万元)': -2.27,
          '拨付金额(万元)': 320.13,
          例均盈亏: -93.62,
        },
        {
          医疗组: '普外科一组',
          病例数: 362,
          病组数: 70,
          CMI: 1.04,
          总权重: 378.2,
          本院例均费用: 7302.62,
          平均住院日: 5.95,
          药品费占比: 14.35,
          材料费占比: 15.21,
          总点数: 36028.31,
          '合计盈亏(万元)': 26.8,
          '拨付金额(万元)': 291.16,
          例均盈亏: 740.45,
        },
        {
          医疗组: '胸部疾病诊疗中心一组',
          病例数: 245,
          病组数: 45,
          CMI: 1.52,
          总权重: 372.36,
          本院例均费用: 13257.93,
          平均住院日: 6.61,
          药品费占比: 14.66,
          材料费占比: 21.87,
          总点数: 39218.87,
          '合计盈亏(万元)': -8.21,
          '拨付金额(万元)': 316.6,
          例均盈亏: -335.3,
        },
        {
          医疗组: '呼吸与危重症医学科二',
          病例数: 478,
          病组数: 54,
          CMI: 0.77,
          总权重: 367.9,
          本院例均费用: 7347.51,
          平均住院日: 8.01,
          药品费占比: 20.91,
          材料费占比: 2.05,
          总点数: 42160.41,
          '合计盈亏(万元)': -8.64,
          '拨付金额(万元)': 342.42,
          例均盈亏: -180.81,
        },
      ],
    },
    columns: {
      type: Object,
      default: () => ({
        //一级表头列表
        columns1: [
          {
            label: '医疗组',
            prop: '医疗组',
            headerFontSize: 14,
            contentFontSize: 14,
            widthPercent: 15,
            pptContentFontSize: 8,
          },
        ],
        //二级表头列表
        columns2: [
          {
            label: '医疗服务能力',
            prop: '医疗服务能力',
            headerFontSize: 14,
            contentFontSize: 14,
            widthPercent: 30,
            pptContentFontSize: 8,
            columns: [
              {
                label: '病例数',
                prop: '病例数',
              },
              {
                label: '病组数',
                prop: '病组数',
              },
              {
                label: 'CMI',
                prop: 'CMI',
              },
              {
                label: '总权重',
                prop: '总权重',
              },
            ],
          },
          {
            label: '医疗效率',
            prop: '医疗效率',
            headerFontSize: 14,
            contentFontSize: 14,
            widthPercent: 30,
            pptContentFontSize: 8,
            columns: [
              {
                label: '本院例均费用',
                prop: '本院例均费用',
              },
              {
                label: '平均住院日',
                prop: '平均住院日',
              },
              {
                label: '药品费占比',
                prop: '药品费占比',
              },
              {
                label: '材料费占比',
                prop: '材料费占比',
              },
            ],
          },
          {
            label: '结算指标',
            prop: '结算指标',
            headerFontSize: 14,
            contentFontSize: 14,
            widthPercent: 30,
            pptContentFontSize: 8,
            columns: [
              {
                label: '总点数',
                prop: '总点数',
              },
              {
                label: '合计盈亏(万元)',
                prop: '合计盈亏(万元)',
              },
              {
                label: '拨付金额(万元)',
                prop: '拨付金额(万元)',
              },
              {
                label: '例均盈亏',
                prop: '例均盈亏',
              },
            ],
          },
        ],
      }),
    },
  },
  methods: {
    /**
     * 颜色变亮方法
     * @param {string} color 16进制颜色值（不含#）
     * @param {number} percent 变亮百分比
     * @returns {string} 变亮后的颜色值
     */
    lightenColor(color, percent) {
      const num = parseInt(color, 16);
      const r = Math.min(255, (num >> 16) + Math.round(255 * (percent / 100)));
      const g = Math.min(255, ((num >> 8) & 0x00ff) + Math.round(255 * (percent / 100)));
      const b = Math.min(255, (num & 0x0000ff) + Math.round(255 * (percent / 100)));
      return ((r << 16) | (g << 8) | b).toString(16).padStart(6, '0');
    },
    formatValue(prop, value) {
      if (value === null || value === undefined) return '';

      // 格式化数值
      if (typeof value === 'number') {
        // 金额类字段保留2位小数
        if (prop.includes('费用') || prop.includes('金额') || prop.includes('盈亏')) {
          return value.toFixed(2);
        }
        // 比率类字段保留2位小数
        if (prop.includes('占比') || prop === 'CMI') {
          return value.toFixed(2);
        }
        // 天数保留2位小数
        if (prop.includes('住院日')) {
          return value.toFixed(2);
        }
        // 整数类字段
        if (prop.includes('病例数') || prop.includes('病组数') || prop.includes('点数') || prop.includes('权重')) {
          return Math.round(value).toLocaleString();
        }
        return value.toFixed(2);
      }

      return value;
    },
    exportToPPT(pptx, slide) {
      let tabOpts1 = {
        x: this.pptOptions.x,
        y: this.pptOptions.y,
        w: this.pptOptions.w,
        h: this.pptOptions.h,
        colW: this.pptOptions.table.colW,
        rowH: this.pptOptions.table.rowH,
        border: {
          pt: 1,
          color: this.pptOptions.table.borderStyle.color,
        },
        align: this.pptOptions.table.align,
        valign: this.pptOptions.table.valign,
        // 自动分页配置
        autoPage: this.pptOptions.table.autoPage,
        autoPageRepeatHeader: this.pptOptions.table.autoPageRepeatHeader,
        autoPageHeaderRows: this.pptOptions.table.autoPageHeaderRows,
      };
      // 动态生成表头
      let arrTabRows1 = [];
      // 第一行表头 - 一级表头和二级表头组
      let firstHeaderRow = [];
      // 添加一级表头
      this.columns.columns1.forEach(col => {
        firstHeaderRow.push({
          text: col.label,
          options: {
            rowspan: 2,
            fill: { color: this.headerBgColor ? this.headerBgColor.replace('#', '') : '4874cb' },
            color: this.pptOptions.table.title.color,
            fontSize: col.pptContentFontSize || this.pptOptions.table.title.fontSize,
            valign: this.pptOptions.table.valign,
            align: this.pptOptions.table.align,
            bold: this.pptOptions.table.content.bold,
          },
        });
      });

      // 添加二级表头组
      this.columns.columns2.forEach(group => {
        firstHeaderRow.push({
          text: group.label,
          options: {
            colspan: group.columns.length,
            fill: { color: this.headerBgColor ? this.headerBgColor.replace('#', '') : '4874cb' },
            color: this.pptOptions.table.title.color,
            fontSize: group.pptContentFontSize || this.pptOptions.table.title.fontSize,
            valign: this.pptOptions.table.valign,
            align: this.pptOptions.table.align,
            bold: this.pptOptions.table.content.bold,
          },
        });
      });
      arrTabRows1.push(firstHeaderRow);
      // 第二行表头 - 二级表头子列
      let secondHeaderRow = [];
      this.columns.columns2.forEach(group => {
        group.columns.forEach(col => {
          // 二级表头使用较浅的颜色，可以通过配置或默认值设置
          const secondaryHeaderColor = this.headerBgColor ? this.lightenColor(this.headerBgColor.replace('#', ''), 30) : '80a1e2';

          secondHeaderRow.push({
            text: col.label,
            options: {
              fill: { color: secondaryHeaderColor },
              color: this.pptOptions.table.title.color,
              fontSize: group.pptContentFontSize || this.pptOptions.table.title.fontSize,
              valign: this.pptOptions.table.valign,
              align: this.pptOptions.table.align,
              bold: this.pptOptions.table.content.bold,
            },
          });
        });
      });
      arrTabRows1.push(secondHeaderRow);
      // 数据行
      this.tableData.forEach((row, index) => {
        let dataRow = [];
        // 判断是否为偶数行（从0开始计数，所以偶数行是0,2,4...）
        const isEvenRow = index % 2 === 0;
        const rowFillColor = isEvenRow ? 'f5f5f5' : 'ffffff';

        // 添加一级列数据（医疗组）
        this.columns.columns1.forEach(col => {
          dataRow.push({
            text: String(row[col.prop] || ''),
            options: {
              fontSize: col.pptContentFontSize || this.pptOptions.table.content.fontSize,
              color: this.pptOptions.table.content.color,
              fill: { color: rowFillColor },
              valign: this.pptOptions.table.valign,
              align: this.pptOptions.table.align,
              bold: this.pptOptions.table.content.bold,
            },
          });
        });
        // 添加二级列数据
        this.columns.columns2.forEach(group => {
          group.columns.forEach(col => {
            let value = this.formatValue(col.prop, row[col.prop]);
            // 检查是否需要标红显示
            const shouldHighlight = row[col.prop + '是否标红'];
            let cellOptions = {
              fontSize: group.pptContentFontSize || this.pptOptions.table.content.fontSize,
              color: shouldHighlight ? 'ee6666' : this.pptOptions.table.content.color,
              fill: { color: rowFillColor },
              valign: this.pptOptions.table.valign,
              align: this.pptOptions.table.align,
              bold: this.pptOptions.table.content.bold,
            };

            dataRow.push({
              text: String(value),
              options: cellOptions,
            });
          });
        });

        arrTabRows1.push(dataRow);
      });

      slide.addTable(arrTabRows1, tabOpts1);
    },
  },
  mounted() {},
};
</script>
<style scoped>
.data-table-many {
  width: 100%;
  height: 100%;
}

.table-header {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 16px;
}

.export-btn {
  background: #4874cb;
  color: white;
  border: none;
  padding: 8px 16px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.3s ease;
}

.export-btn:hover {
  background: #3a5fb0;
}

.export-btn:active {
  background: #2d4a8a;
}

.medical-table {
  width: 100%;
  height: 100%;
  border-collapse: collapse;
  background: white;
  overflow: hidden;
}

/* 表头样式 */
.header-cell {
  background: #4874cb;
  color: white;
  font-weight: bold;
  text-align: center;
  padding: 12px 8px;
  border: 1px solid #000;
  min-height: 45px;
  position: relative;
}

.header-cell.level-1 {
  background: #4874cb;
}

.header-cell.level-2 {
  background: #80a1e2;
  padding: 10px 6px;
}

/* 数据行样式 */
.data-row {
  transition: background-color 0.2s ease;
}

.data-row:hover {
  background-color: #f7fafc;
}

.row-even {
  background-color: #ffffff;
}

.row-odd {
  background-color: #f8f9fa;
}

/* 数据单元格样式 */
.data-cell {
  padding: 10px 8px;
  text-align: center;
  border: 1px solid #000;
  color: #000;
  font-weight: 600;
  vertical-align: middle;
}

.data-cell.medical-group {
  background-color: #fff;
  font-weight: 600;
  color: #000;
  text-align: center;
  padding-left: 12px;
}

/* 数值样式 */
.positive-value {
  color: #38a169;
  font-weight: 600;
}

.negative-value {
  color: #e53e3e;
  font-weight: 600;
}

/* 滚动条样式 */
.data-table-many::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

.data-table-many::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 4px;
}

.data-table-many::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 4px;
}

.data-table-many::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}
</style>
